/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "zip.h"

namespace filter
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    zip::zip() : BASE( CLASS_NAME( zip ) )
    {
        init_data();
    }

    zip::~zip()
    {
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    icat::i_plugin::enumRetCode zip::proc_task( icat::i_task * pTask )
    {
        icat::i_plugin::enumRetCode result = icat::i_plugin::RET_CODE_DONE;
        icat::i_response * pResponse = pTask->get_response();
        icat::i_request * pRequest = pTask->get_request();
        xos_common::i_property * pResTag = pResponse->get_tag();
        xos_common::i_property * pReqTag = pRequest->get_tag();
        xos::i_list * pResData = pResponse->get_data();
        icat::i_chain * pChain = pTask->get_chain();
        int ret = 0;

        if( ( 0 == ret ) && !pChain->is_go_back() )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            int nLen = 0;
            for( pResData->reset(); pResData->data(); pResData->next() )
            {
                xos::i_buf * pBuf = ( xos::i_buf * )pResData->data();
                nLen += pBuf->get_len( 0 );
            }
            if( nLen < compress_size )
            {
                ret = 1;
            }
        }
        
        if( 0 == ret )
        {
            const char * lpszAccept = pReqTag->str( xos_http::HTTP_ACCEPT_ENCODING );
            if( !lpszAccept || !container()->crt()->strstr( lpszAccept, xos_http::HTTP_ZIP_DEFLATE, true ) )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            const char * lpszEncod = pResTag->str( xos_http::HTTP_CONTENT_ENCODING );
            if( lpszEncod )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            const char * lpszType = pResTag->str( xos_http::HTTP_CONTENT_TYPE );
            if( !lpszType || !can_compress( lpszType ) )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            compress( pResponse );
        }

        return result;
    }

    bool zip::can_compress( const char * lpszFmt )
    {
        bool bRet = false;

        STR_ITER iter = m_map.find( lpszFmt );
        if( iter != m_map.end() )
        {
            bRet = true;
        }

        return bRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int zip::compress( icat::i_response * pResponse )
    {
        int ret = 0;

        xos_common::i_property * pResTag = pResponse->get_tag();
        xos::i_list * pResData = pResponse->get_data();
        xos_compress::i_compress * pZlib = 0;
        xos::i_list * pList = 0;

        if( 0 == ret )
        {
            container()->compress()->create( xos_compress::OBJ_ZLIB, ( void** )&pZlib );
            container()->xos()->create( xos::i_xos::XOS_OBJ_LIST, ( void** )&pList );
        }

        if( 0 == ret )
        {
            pZlib->compress( pList, pResData );
            pList->swap( pResData );
        }

        if( 0 == ret )
        {
            pResTag->set( xos_http::HTTP_CONTENT_ENCODING, xos_http::HTTP_ZIP_DEFLATE );
        }

        xos_stl::release_interface( pZlib );
        xos_stl::release_interface( pList );

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int zip::init_data()
    {
        int ret = 0;

        compress_size = 4096;
        m_map.clear();

        return ret;
    }

    int zip::init_obj()
    {
        int ret = 0;

        xos::i_list * pFmtList;

        xos_common::i_property * pProp = config::prop()->prop( "filters" )->prop( "zip" );
        {
            compress_size = pProp->it( "compress_size" );
            pFmtList = pProp->list( "fmts" );
        }

        for( pFmtList->reset(); pFmtList->data(); pFmtList->next() )
        {
            xos_common::i_variant * pVT = ( xos_common::i_variant * )pFmtList->data();
            m_map[pVT->str()] = 1;
        }

        return ret;
    }

    int zip::term_obj()
    {
        int ret = 0;
        init_data();
        return ret;
    }

} // filter
